Trò chơi Tic-Tac-Toe, game đánh caro full source code
- LoadbalancingPeer.cs
- PhotonNetwork /
- Plugins /
- Photon Unity Networking /
- Assets /
- project /
2 // <copyright file="LoadbalancingPeer.cs" company="Exit Games GmbH">
3 // Loadbalancing Framework for Photon - Copyright (C) 2011 Exit Games GmbH
4 // </copyright>
5 // <summary>
6 // Provides the operations needed to use the loadbalancing server app(s).
7 // </summary>
8 // <author>developer@exitgames.com</author>
9 // ----------------------------------------------------------------------------
10
11 using ExitGames.Client.Photon;
12 using ExitGames.Client.Photon.Lite;
13 using System;
14 using System.Collections.Generic;
15 using Hashtable = ExitGames.Client.Photon.Hashtable;
16
17
18 namespace ExitGames.Client.Photon
19 {
20 /// <summary>
21 /// Internally used by PUN, a LoadbalancingPeer provides the operations and enum
22 /// definitions needed to use the Photon Loadbalancing server (or the Photon Cloud).
23 /// </summary>
24 /// <remarks>
25 /// The LoadBalancingPeer does not keep a state, instead this is done by a LoadBalancingClient.
26 /// </remarks>
27 internal class LoadbalancingPeer : PhotonPeer
28 {
29 private readonly Dictionary<byte, object> opParameters = new Dictionary<byte, object>(); // used in OpRaiseEvent() (avoids lots of new Dictionary() calls)
30
31 public LoadbalancingPeer(IPhotonPeerListener listener, ConnectionProtocol protocolType) : base(listener, protocolType)
32 {
33 }
34
35 public virtual bool OpGetRegions(string appId)
36 {
37 Dictionary<byte, object> parameters = new Dictionary<byte, object>();
38 parameters[(byte)ParameterCode.ApplicationId] = appId;
39
40 return this.OpCustom(OperationCode.GetRegions, parameters, true, 0, true);
41 }
42
43 /// <summary>
44 /// Joins the lobby on the Master Server, where you get a list of RoomInfos of currently open rooms.
45 /// This is an async request which triggers a OnOperationResponse() call.
46 /// </summary>
47 /// <returns>If the operation could be sent (has to be connected).</returns>
48 public virtual bool OpJoinLobby(TypedLobby lobby)
49 {
50 if (this.DebugOut >= DebugLevel.INFO)
51 {
52 this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinLobby()");
53 }
54
55 Dictionary<byte, object> parameters = null;
56 if (lobby != null && !lobby.IsDefault)
57 {
58 parameters = new Dictionary<byte, object>();
59 parameters[(byte)ParameterCode.LobbyName] = lobby.Name;
60 parameters[(byte)ParameterCode.LobbyType] = (byte)lobby.Type;
61 }
62
63 return this.OpCustom(OperationCode.JoinLobby, parameters, true);
64 }
65
66 /// <summary>
67 /// Leaves the lobby on the Master Server.
68 /// This is an async request which triggers a OnOperationResponse() call.
69 /// </summary>
70 /// <returns>If the operation could be sent (has to be connected).</returns>
71 public virtual bool OpLeaveLobby()
72 {
73 if (this.DebugOut >= DebugLevel.INFO)
74 {
75 this.Listener.DebugReturn(DebugLevel.INFO, "OpLeaveLobby()");
76 }
77
78 return this.OpCustom(OperationCode.LeaveLobby, null, true);
79 }
80
81
82 /// <summary>
83 /// Don't use this method directly, unless you know how to cache and apply customActorProperties.
84 /// The PhotonNetwork methods will handle player and room properties for you and call this method.
85 /// </summary>
86 public virtual bool OpCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby lobby, Hashtable playerProperties, bool onGameServer)
87 {
88 if (this.DebugOut >= DebugLevel.INFO)
89 {
90 this.Listener.DebugReturn(DebugLevel.INFO, "OpCreateRoom()");
91 }
92
93 Dictionary<byte, object> op = new Dictionary<byte, object>();
94
95 if (!string.IsNullOrEmpty(roomName))
96 {
97 op[ParameterCode.RoomName] = roomName;
98 }
99 if (lobby != null)
100 {
101 op[ParameterCode.LobbyName] = lobby.Name;
102 op[ParameterCode.LobbyType] = (byte)lobby.Type;
103 }
104
105 if (onGameServer)
106 {
107 if (playerProperties != null && playerProperties.Count > 0)
108 {
109 op[ParameterCode.PlayerProperties] = playerProperties;
110 op[ParameterCode.Broadcast] = true; // TODO: check if this also makes sense when creating a room?! // broadcast actor properties
111 }
112
113
114 if (roomOptions == null)
115 {
116 roomOptions = new RoomOptions();
117 }
118
119 Hashtable gameProperties = new Hashtable();
120 op[ParameterCode.GameProperties] = gameProperties;
121 gameProperties.MergeStringKeys(roomOptions.customRoomProperties);
122
123 gameProperties[GameProperties.IsOpen] = roomOptions.isOpen; // TODO: check default value. dont send this then
124 gameProperties[GameProperties.IsVisible] = roomOptions.isVisible; // TODO: check default value. dont send this then
125 gameProperties[GameProperties.PropsListedInLobby] = roomOptions.customRoomPropertiesForLobby;
126 if (roomOptions.maxPlayers > 0)
127 {
128 gameProperties[GameProperties.MaxPlayers] = roomOptions.maxPlayers;
129 }
130 if (roomOptions.cleanupCacheOnLeave)
131 {
132 op[ParameterCode.CleanupCacheOnLeave] = true; // this is actually setting the room's config
133 gameProperties[GameProperties.CleanupCacheOnLeave] = true; // this is only informational for the clients which join
134 }
135 }
136
137 // UnityEngine.Debug.Log("CreateGame: " + SupportClass.DictionaryToString(op));
138 return this.OpCustom(OperationCode.CreateGame, op, true);
139 }
140
141
142 /// <summary>LoadBalancingPeer.OpJoinRoom</summary>
143 public virtual bool OpJoinRoom(string roomName, RoomOptions roomOptions, TypedLobby lobby, bool createIfNotExists, Hashtable playerProperties, bool onGameServer)
144 {
145 Dictionary<byte, object> op = new Dictionary<byte, object>();
146
147 if (!string.IsNullOrEmpty(roomName))
148 {
149 op[ParameterCode.RoomName] = roomName;
150 }
151 if (createIfNotExists)
152 {
153 op[ParameterCode.CreateIfNotExists] = true;
154 if (lobby != null)
155 {
156 op[ParameterCode.LobbyName] = lobby.Name;
157 op[ParameterCode.LobbyType] = (byte)lobby.Type;
158 }
159 }
160
161 if (onGameServer)
162 {
163 if (playerProperties != null && playerProperties.Count > 0)
164 {
165 op[ParameterCode.PlayerProperties] = playerProperties;
166 op[ParameterCode.Broadcast] = true; // broadcast actor properties
167 }
168
169
170 if (createIfNotExists)
171 {
172 if (roomOptions == null)
173 {
174 roomOptions = new RoomOptions();
175 }
176
177 Hashtable gameProperties = new Hashtable();
178 op[ParameterCode.GameProperties] = gameProperties;
179 gameProperties.MergeStringKeys(roomOptions.customRoomProperties);
180
181 gameProperties[GameProperties.IsOpen] = roomOptions.isOpen;
182 gameProperties[GameProperties.IsVisible] = roomOptions.isVisible;
183 gameProperties[GameProperties.PropsListedInLobby] = roomOptions.customRoomPropertiesForLobby;
184 if (roomOptions.maxPlayers > 0)
185 {
186 gameProperties[GameProperties.MaxPlayers] = roomOptions.maxPlayers;
187 }
188 if (roomOptions.cleanupCacheOnLeave)
189 {
190 op[ParameterCode.CleanupCacheOnLeave] = true; // this is actually setting the room's config
191 gameProperties[GameProperties.CleanupCacheOnLeave] = true; // this is only informational for the clients which join
192 }
193 }
194 }
195
196 // UnityEngine.Debug.Log("JoinGame: " + SupportClass.DictionaryToString(op));
197 return this.OpCustom(OperationCode.JoinGame, op, true);
198 }
199
200
201 /// <summary>
202 /// Operation to join a random, available room. Overloads take additional player properties.
203 /// This is an async request which triggers a OnOperationResponse() call.
204 /// If all rooms are closed or full, the OperationResponse will have a returnCode of ErrorCode.NoRandomMatchFound.
205 /// If successful, the OperationResponse contains a gameserver address and the name of some room.
206 /// </summary>
207 /// <param name="expectedCustomRoomProperties">Optional. A room will only be joined, if it matches these custom properties (with string keys).</param>
208 /// <param name="expectedMaxPlayers">Filters for a particular maxplayer setting. Use 0 to accept any maxPlayer value.</param>
209 /// <param name="playerProperties">This player's properties (custom and well known).</param>
210 /// <param name="matchingType">Selects one of the available matchmaking algorithms. See MatchmakingMode enum for options.</param>
211 /// <returns>If the operation could be sent currently (requires connection).</returns>
212 public virtual bool OpJoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, Hashtable playerProperties, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter)
213 {
214 if (this.DebugOut >= DebugLevel.INFO)
215 {
216 this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinRandomRoom()");
217 }
218
219 Hashtable expectedRoomProperties = new Hashtable();
220 expectedRoomProperties.MergeStringKeys(expectedCustomRoomProperties);
221 if (expectedMaxPlayers > 0)
222 {
223 expectedRoomProperties[GameProperties.MaxPlayers] = expectedMaxPlayers;
224 }
225
226 Dictionary<byte, object> opParameters = new Dictionary<byte, object>();
227 if (expectedRoomProperties.Count > 0)
228 {
229 opParameters[ParameterCode.GameProperties] = expectedRoomProperties;
230 }
231
232 if (playerProperties != null && playerProperties.Count > 0)
233 {
234 opParameters[ParameterCode.PlayerProperties] = playerProperties;
235 }
236
237 if (matchingType != MatchmakingMode.FillRoom)
238 {
239 opParameters[ParameterCode.MatchMakingType] = (byte)matchingType;
240 }
241
242 if (typedLobby != null)
243 {
244 opParameters[ParameterCode.LobbyName] = typedLobby.Name;
245 opParameters[ParameterCode.LobbyType] = (byte)typedLobby.Type;
246 }
247
248 if (!string.IsNullOrEmpty(sqlLobbyFilter))
249 {
250 opParameters[ParameterCode.Data] = sqlLobbyFilter;
251 }
252
253 // UnityEngine.Debug.LogWarning("OpJoinRandom: " + opParameters.ToStringFull());
254 return this.OpCustom(OperationCode.JoinRandomGame, opParameters, true);
255 }
256
257 /// <summary>
258 /// Request the rooms and online status for a list of friends (each client must set a unique username via OpAuthenticate).
259 /// </summary>
260 /// <remarks>
261 /// Used on Master Server to find the rooms played by a selected list of users.
262 /// Users identify themselves by using OpAuthenticate with a unique username.
263 /// The list of usernames must be fetched from some other source (not provided by Photon).
264 ///
265 /// The server response includes 2 arrays of info (each index matching a friend from the request):
266 /// ParameterCode.FindFriendsResponseOnlineList = bool[] of online states
267 /// ParameterCode.FindFriendsResponseRoomIdList = string[] of room names (empty string if not in a room)
268 /// </remarks>
269 /// <param name="friendsToFind">Array of friend's names (make sure they are unique).</param>
270 /// <returns>If the operation could be sent (requires connection).</returns>
271 public virtual bool OpFindFriends(string[] friendsToFind)
272 {
273 Dictionary<byte, object> opParameters = new Dictionary<byte, object>();
274 if (friendsToFind != null && friendsToFind.Length > 0)
275 {
276 opParameters[ParameterCode.FindFriendsRequestList] = friendsToFind;
277 }
278
279 return this.OpCustom(OperationCode.FindFriends, opParameters, true);
280 }
281
282 public bool OpSetCustomPropertiesOfActor(int actorNr, Hashtable actorProperties, bool broadcast, byte channelId)
283 {
284 return this.OpSetPropertiesOfActor(actorNr, actorProperties.StripToStringKeys(), broadcast, channelId);
285 }
286
287 protected bool OpSetPropertiesOfActor(int actorNr, Hashtable actorProperties, bool broadcast, byte channelId)
288 {
289 if (this.DebugOut >= DebugLevel.INFO)
290 {
291 this.Listener.DebugReturn(DebugLevel.INFO, "OpSetPropertiesOfActor()");
292 }
293
294 if (actorNr <= 0 || actorProperties == null)
295 {
296 if (this.DebugOut >= DebugLevel.INFO)
297 {
298 this.Listener.DebugReturn(DebugLevel.INFO, "OpSetPropertiesOfActor not sent. ActorNr must be > 0 and actorProperties != null.");
299 }
300 return false;
301 }
302
303 Dictionary<byte, object> opParameters = new Dictionary<byte, object>();
304 opParameters.Add(ParameterCode.Properties, actorProperties);
305 opParameters.Add(ParameterCode.ActorNr, actorNr);
306 if (broadcast)
307 {
308 opParameters.Add(ParameterCode.Broadcast, broadcast);
309 }
310
311 return this.OpCustom((byte)OperationCode.SetProperties, opParameters, broadcast, channelId);
312 }
313
314 protected void OpSetPropertyOfRoom(byte propCode, object value)
315 {
316 Hashtable properties = new Hashtable();
317 properties[propCode] = value;
318 this.OpSetPropertiesOfRoom(properties, true, (byte)0);
319 }
320
321 public bool OpSetCustomPropertiesOfRoom(Hashtable gameProperties, bool broadcast, byte channelId)
322 {
323 return this.OpSetPropertiesOfRoom(gameProperties.StripToStringKeys(), broadcast, channelId);
324 }
325
326 public bool OpSetPropertiesOfRoom(Hashtable gameProperties, bool broadcast, byte channelId)
327 {
328 if (this.DebugOut >= DebugLevel.INFO)
329 {
330 this.Listener.DebugReturn(DebugLevel.INFO, "OpSetPropertiesOfRoom()");
331 }
332
333 Dictionary<byte, object> opParameters = new Dictionary<byte, object>();
334 opParameters.Add(ParameterCode.Properties, gameProperties);
335 if (broadcast)
336 {
337 opParameters.Add(ParameterCode.Broadcast, true);
338 }
339
340 return this.OpCustom((byte)OperationCode.SetProperties, opParameters, broadcast, channelId);
341 }
342
343 /// <summary>
344 /// Sends this app's appId and appVersion to identify this application server side.
345 /// This is an async request which triggers a OnOperationResponse() call.
346 /// </summary>
347 /// <remarks>
348 /// This operation makes use of encryption, if that is established before.
349 /// See: EstablishEncryption(). Check encryption with IsEncryptionAvailable.
350 /// This operation is allowed only once per connection (multiple calls will have ErrorCode != Ok).
351 /// </remarks>
352 /// <param name="appId">Your application's name or ID to authenticate. This is assigned by Photon Cloud (webpage).</param>
353 /// <param name="appVersion">The client's version (clients with differing client appVersions are separated and players don't meet).</param>
354 /// <param name="userId"></param>
355 /// <param name="authValues"></param>
356 /// <param name="regionCode">When authenticating for a specific region, a NameServer will forward you to that region's MasterServer.</param>
357 /// <returns>If the operation could be sent (has to be connected).</returns>
358 public virtual bool OpAuthenticate(string appId, string appVersion, string userId, AuthenticationValues authValues, string regionCode)
359 {
360 if (this.DebugOut >= DebugLevel.INFO)
361 {
362 this.Listener.DebugReturn(DebugLevel.INFO, "OpAuthenticate()");
363 }
364
365 Dictionary<byte, object> opParameters = new Dictionary<byte, object>();
366 if (authValues != null && authValues.Secret != null)
367 {
368 opParameters[ParameterCode.Secret] = authValues.Secret;
369 return this.OpCustom(OperationCode.Authenticate, opParameters, true, (byte)0, false);
370 }
371
372 opParameters[ParameterCode.AppVersion] = appVersion;
373 opParameters[ParameterCode.ApplicationId] = appId;
374
375 if (!string.IsNullOrEmpty(regionCode))
376 {
377 opParameters[ParameterCode.Region] = regionCode;
378 }
379
380 if (!string.IsNullOrEmpty(userId))
381 {
382 opParameters[ParameterCode.UserId] = userId;
383 }
384
385
386 if (authValues != null && authValues.AuthType != CustomAuthenticationType.None)
387 {
388 if (!this.IsEncryptionAvailable)
389 {
390 this.Listener.DebugReturn(DebugLevel.ERROR, "OpAuthenticate() failed. When you want Custom Authentication encryption is mandatory.");
391 return false;
392 }
393
394 opParameters[ParameterCode.ClientAuthenticationType] = (byte)authValues.AuthType;
395 if (!string.IsNullOrEmpty(authValues.Secret))
396 {
397 opParameters[ParameterCode.Secret] = authValues.Secret;
398 }
399 //else
400 //{
401 if (!string.IsNullOrEmpty(authValues.AuthParameters))
402 {
403 opParameters[ParameterCode.ClientAuthenticationParams] = authValues.AuthParameters;
404 }
405 if (authValues.AuthPostData != null)
406 {
407 opParameters[ParameterCode.ClientAuthenticationData] = authValues.AuthPostData;
408 }
409 //}
410 }
411
412 bool sent = this.OpCustom(OperationCode.Authenticate, opParameters, true, (byte)0, this.IsEncryptionAvailable);
413 if (!sent)
414 {
415 this.Listener.DebugReturn(DebugLevel.ERROR, "Error calling OpAuthenticate! Did not work. Check log output, CustomAuthenticationValues and if you're connected.");
416 }
417 return sent;
418 }
419
420
421 /// <summary>
422 /// Operation to handle this client's interest groups (for events in room).
423 /// </summary>
424 /// <remarks>
425 /// Note the difference between passing null and byte[0]:
426 /// null won't add/remove any groups.
427 /// byte[0] will add/remove all (existing) groups.
428 /// First, removing groups is executed. This way, you could leave all groups and join only the ones provided.
429 /// </remarks>
430 /// <param name="groupsToRemove">Groups to remove from interest. Null will not remove any. A byte[0] will remove all.</param>
431 /// <param name="groupsToAdd">Groups to add to interest. Null will not add any. A byte[0] will add all current.</param>
432 /// <returns></returns>
433 public virtual bool OpChangeGroups(byte[] groupsToRemove, byte[] groupsToAdd)
434 {
435 if (this.DebugOut >= DebugLevel.ALL)
436 {
437 this.Listener.DebugReturn(DebugLevel.ALL, "OpChangeGroups()");
438 }
439
440 Dictionary<byte, object> opParameters = new Dictionary<byte, object>();
441 if (groupsToRemove != null)
442 {
443 opParameters[(byte)LiteOpKey.Remove] = groupsToRemove;
444 }
445 if (groupsToAdd != null)
446 {
447 opParameters[(byte)LiteOpKey.Add] = groupsToAdd;
448 }
449
450 return this.OpCustom((byte)LiteOpCode.ChangeGroups, opParameters, true, 0);
451 }
452
453
454 /// <summary>
455 /// Send an event with custom code/type and any content to the other players in the same room.
456 /// </summary>
457 /// <remarks>This override explicitly uses another parameter order to not mix it up with the implementation for Hashtable only.</remarks>
458 /// <param name="eventCode">Identifies this type of event (and the content). Your game's event codes can start with 0.</param>
459 /// <param name="customEventContent">Any serializable datatype (including Hashtable like the other OpRaiseEvent overloads).</param>
460 /// <param name="sendReliable">If this event has to arrive reliably (potentially repeated if it's lost).</param>
461 /// <param name="raiseEventOptions">Contains (slightly) less often used options. If you pass null, the default options will be used.</param>
462 /// <returns>If operation could be enqueued for sending. Sent when calling: Service or SendOutgoingCommands.</returns>
463 public virtual bool OpRaiseEvent(byte eventCode, object customEventContent, bool sendReliable, RaiseEventOptions raiseEventOptions)
464 {
465 opParameters.Clear(); // re-used private variable to avoid many new Dictionary() calls (garbage collection)
466 opParameters[(byte)LiteOpKey.Code] = (byte)eventCode;
467 if (customEventContent != null)
468 {
469 opParameters[(byte) LiteOpKey.Data] = customEventContent;
470 }
471
472 if (raiseEventOptions == null)
473 {
474 raiseEventOptions = RaiseEventOptions.Default;
475 }
476 else
477 {
478 if (raiseEventOptions.CachingOption != EventCaching.DoNotCache)
479 {
480 opParameters[(byte) LiteOpKey.Cache] = (byte) raiseEventOptions.CachingOption;
481 }
482 if (raiseEventOptions.Receivers != ReceiverGroup.Others)
483 {
484 opParameters[(byte) LiteOpKey.ReceiverGroup] = (byte) raiseEventOptions.Receivers;
485 }
486 if (raiseEventOptions.InterestGroup != 0)
487 {
488 opParameters[(byte) LiteOpKey.Group] = (byte) raiseEventOptions.InterestGroup;
489 }
490 if (raiseEventOptions.TargetActors != null)
491 {
492 opParameters[(byte) LiteOpKey.ActorList] = raiseEventOptions.TargetActors;
493 }
494 if (raiseEventOptions.ForwardToWebhook)
495 {
496 opParameters[(byte) ParameterCode.EventForward] = true; //TURNBASED
497 }
498 }
499
500 return this.OpCustom((byte)LiteOpCode.RaiseEvent, opParameters, sendReliable, raiseEventOptions.SequenceChannel, raiseEventOptions.Encrypt);
501 }
502 }
503
504
505 /// <summary>
506 /// Class for constants. These (int) values represent error codes, as defined and sent by the Photon LoadBalancing logic.
507 /// Pun uses these constants internally.
508 /// </summary>
509 /// <remarks>Codes from the Photon Core are negative. Default-app error codes go down from short.max.</remarks>
510 internal class ErrorCode
511 {
512 /// <summary>(0) is always "OK", anything else an error or specific situation.</summary>
513 public const int Ok = 0;
514
515 // server - Photon low(er) level: <= 0
516
517 /// <summary>
518 /// (-3) Operation can't be executed yet (e.g. OpJoin can't be called before being authenticated, RaiseEvent cant be used before getting into a room).
519 /// </summary>
520 /// <remarks>
521 /// Before you call any operations on the Cloud servers, the automated client workflow must complete its authorization.
522 /// In PUN, wait until State is: JoinedLobby (with AutoJoinLobby = true) or ConnectedToMaster (AutoJoinLobby = false)
523 /// </remarks>
524 public const int OperationNotAllowedInCurrentState = -3;
525
526 /// <summary>(-2) The operation you called is not implemented on the server (application) you connect to. Make sure you run the fitting applications.</summary>
527 public const int InvalidOperationCode = -2;
528
529 /// <summary>(-1) Something went wrong in the server. Try to reproduce and contact Exit Games.</summary>
530 public const int InternalServerError = -1;
531
532 // server - PhotonNetwork: 0x7FFF and down
533 // logic-level error codes start with short.max
534
535 /// <summary>(32767) Authentication failed. Possible cause: AppId is unknown to Photon (in cloud service).</summary>
536 public const int InvalidAuthentication = 0x7FFF;
537
538 /// <summary>(32753) The Authentication ticket expired. Usually, this is refreshed behind the scenes. Connect (and authorize) again.</summary>
539 public const int AuthenticationTicketExpired = 0x7FF1;
540
541 /// <summary>(32766) GameId (name) already in use (can't create another). Change name.</summary>
542 public const int GameIdAlreadyExists = 0x7FFF - 1;
543
544 /// <summary>(32765) Game is full. This rarely happens when some player joined the room before your join completed.</summary>
545 public const int GameFull = 0x7FFF - 2;
546
547 /// <summary>(32764) Game is closed and can't be joined. Join another game.</summary>
548 public const int GameClosed = 0x7FFF - 3;
549
550 [Obsolete("No longer used, cause random matchmaking is no longer a process.")] public const int AlreadyMatched =
551 0x7FFF - 4;
552
553 /// <summary>(32762) Not in use currently.</summary>
554 public const int ServerFull = 0x7FFF - 5;
555
556 /// <summary>(32761) Not in use currently.</summary>
557 public const int UserBlocked = 0x7FFF - 6;
558
559 /// <summary>(32760) Random matchmaking only succeeds if a room exists thats neither closed nor full. Repeat in a few seconds or create a new room.</summary>
560 public const int NoRandomMatchFound = 0x7FFF - 7;
561
562 /// <summary>(32758) Join can fail if the room (name) is not existing (anymore). This can happen when players leave while you join.</summary>
563 public const int GameDoesNotExist = 0x7FFF - 9;
564
565 /// <summary>(32757) Authorization on the Photon Cloud failed because the concurrent users (CCU) limit of the app's subscription is reached.</summary>
566 /// <remarks>
567 /// Unless you have a plan with "CCU Burst", clients might fail the authentication step during connect.
568 /// Affected client are unable to call operations. Please note that players who end a game and return
569 /// to the master server will disconnect and re-connect, which means that they just played and are rejected
570 /// in the next minute / re-connect.
571 /// This is a temporary measure. Once the CCU is below the limit, players will be able to connect an play again.
572 ///
573 /// OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen.
574 /// Self-hosted Photon servers with a CCU limited license won't let a client connect at all.
575 /// </remarks>
576 public const int MaxCcuReached = 0x7FFF - 10;
577
578 /// <summary>(32756) Authorization on the Photon Cloud failed because the app's subscription does not allow to use a particular region's server.</summary>
579 /// <remarks>
580 /// Some subscription plans for the Photon Cloud are region-bound. Servers of other regions can't be used then.
581 /// Check your master server address and compare it with your Photon Cloud Dashboard's info.
582 /// https://cloud.exitgames.com/dashboard
583 ///
584 /// OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen.
585 /// Self-hosted Photon servers with a CCU limited license won't let a client connect at all.
586 /// </remarks>
587 public const int InvalidRegion = 0x7FFF - 11;
588
589 /// <summary>
590 /// (32755) Custom Authentication of the user failed due to setup reasons (see Cloud Dashboard) or the provided user data (like username or token). Check error message for details.
591 /// </summary>
592 public const int CustomAuthenticationFailed = 0x7FFF - 12;
593
594 /// <summary>
595 /// (32752) Also known as "PluginReportedError". A call to an external web service (WebHook) failed and in turn, caused the operation to fail. Check the debug message (increase the logging level, if needed).
596 /// </summary>
597 public const int WebHookCallFailed = 0x7FFF - 15;
598 }
599
600
601 /// <summary>
602 /// Class for constants. These (byte) values define "well known" properties for an Actor / Player.
603 /// Pun uses these constants internally.
604 /// </summary>
605 /// <remarks>
606 /// "Custom properties" have to use a string-type as key. They can be assigned at will.
607 /// </remarks>
608 public class ActorProperties
609 {
610 /// <summary>(255) Name of a player/actor.</summary>
611 public const byte PlayerName = 255; // was: 1
612
613 /// <summary>(254) Tells you if the player is currently in this game (getting events live).</summary>
614 /// <remarks>A server-set value for async games, where players can leave the game and return later.</remarks>
615 public const byte IsInactive = 254;
616 }
617
618
619 /// <summary>
620 /// Class for constants. These (byte) values are for "well known" room/game properties used in Photon Loadbalancing.
621 /// Pun uses these constants internally.
622 /// </summary>
623 /// <remarks>
624 /// "Custom properties" have to use a string-type as key. They can be assigned at will.
625 /// </remarks>
626 public class GameProperties
627 {
628 /// <summary>(255) Max number of players that "fit" into this room. 0 is for "unlimited".</summary>
629 public const byte MaxPlayers = 255;
630 /// <summary>(254) Makes this room listed or not in the lobby on master.</summary>
631 public const byte IsVisible = 254;
632 /// <summary>(253) Allows more players to join a room (or not).</summary>
633 public const byte IsOpen = 253;
634 /// <summary>(252) Current count of players in the room. Used only in the lobby on master.</summary>
635 public const byte PlayerCount = 252;
636 /// <summary>(251) True if the room is to be removed from room listing (used in update to room list in lobby on master)</summary>
637 public const byte Removed = 251;
638 /// <summary>(250) A list of the room properties to pass to the RoomInfo list in a lobby. This is used in CreateRoom, which defines this list once per room.</summary>
639 public const byte PropsListedInLobby = 250;
640 /// <summary>(249) Equivalent of Operation Join parameter CleanupCacheOnLeave.</summary>
641 public const byte CleanupCacheOnLeave = 249;
642 }
643
644
645 /// <summary>
646 /// Class for constants. These values are for events defined by Photon Loadbalancing.
647 /// Pun uses these constants internally.
648 /// </summary>
649 /// <remarks>They start at 255 and go DOWN. Your own in-game events can start at 0.</remarks>
650 public class EventCode
651 {
652 /// <summary>(230) Initial list of RoomInfos (in lobby on Master)</summary>
653 public const byte GameList = 230;
654 /// <summary>(229) Update of RoomInfos to be merged into "initial" list (in lobby on Master)</summary>
655 public const byte GameListUpdate = 229;
656 /// <summary>(228) Currently not used. State of queueing in case of server-full</summary>
657 public const byte QueueState = 228;
658 /// <summary>(227) Currently not used. Event for matchmaking</summary>
659 public const byte Match = 227;
660 /// <summary>(226) Event with stats about this application (players, rooms, etc)</summary>
661 public const byte AppStats = 226;
662 /// <summary>(224) This event provides a list of lobbies with their player and game counts.</summary>
663 public const byte TypedLobbyStats = 224;
664 /// <summary>(210) Internally used in case of hosting by Azure</summary>
665 [Obsolete("TCP routing was removed after becoming obsolete.")]
666 public const byte AzureNodeInfo = 210;
667 /// <summary>(255) Event Join: someone joined the game. The new actorNumber is provided as well as the properties of that actor (if set in OpJoin).</summary>
668 public const byte Join = (byte)LiteEventCode.Join;
669 /// <summary>(254) Event Leave: The player who left the game can be identified by the actorNumber.</summary>
670 public const byte Leave = (byte)LiteEventCode.Leave;
671 /// <summary>(253) When you call OpSetProperties with the broadcast option "on", this event is fired. It contains the properties being set.</summary>
672 public const byte PropertiesChanged = (byte)LiteEventCode.PropertiesChanged;
673 /// <summary>(253) When you call OpSetProperties with the broadcast option "on", this event is fired. It contains the properties being set.</summary>
674 [Obsolete("Use PropertiesChanged now.")]
675 public const byte SetProperties = (byte)LiteEventCode.PropertiesChanged;
676 }
677
678
679 /// <summary>
680 /// Class for constants. Codes for parameters of Operations and Events.
681 /// Pun uses these constants internally.
682 /// </summary>
683 public class ParameterCode
684 {
685 /// <summary>(237) Optional parameter to suppress events Join and Leave for a room (which might be used as lobby/chat room then).</summary>
686 public const byte SuppressRoomEvents = 237;
687 /// <summary>(234) Optional parameter of OpRaiseEvent to forward the event to some web-service.</summary>
688 public const byte EventForward = 234;
689
690 /// <summary>(233) Used in EvLeave to describe if a user is inactive (and might come back) or not. In async / Turnbased games, inactive is default.</summary>
691 public const byte IsInactive = (byte)233;
692
693 /// <summary>(232) Used when creating rooms to define if any userid can join the room only once.</summary>
694 public const byte CheckUserOnJoin = (byte)232;
695
696 /// <summary>(230) Address of a (game) server to use.</summary>
697 public const byte Address = 230;
698 /// <summary>(229) Count of players in rooms (connected to game servers for this application, used in stats event)</summary>
699 public const byte PeerCount = 229;
700 /// <summary>(228) Count of games in this application (used in stats event)</summary>
701 public const byte GameCount = 228;
702 /// <summary>(227) Count of players on the master server (connected to master server for this application, looking for games, used in stats event)</summary>
703 public const byte MasterPeerCount = 227;
704 /// <summary>(225) User's ID</summary>
705 public const byte UserId = 225;
706 /// <summary>(224) Your application's ID: a name on your own Photon or a GUID on the Photon Cloud</summary>
707 public const byte ApplicationId = 224;
708 /// <summary>(223) Not used (as "Position" currently). If you get queued before connect, this is your position</summary>
709 public const byte Position = 223;
710 /// <summary>(223) Modifies the matchmaking algorithm used for OpJoinRandom. Allowed parameter values are defined in enum MatchmakingMode.</summary>
711 public const byte MatchMakingType = 223;
712 /// <summary>(222) List of RoomInfos about open / listed rooms</summary>
713 public const byte GameList = 222;
714 /// <summary>(221) Internally used to establish encryption</summary>
715 public const byte Secret = 221;
716 /// <summary>(220) Version of your application</summary>
717 public const byte AppVersion = 220;
718
719 // Codes for Azure / TCP Proxy are removed
720
721 /// <summary>(255) Code for the gameId/roomName (a unique name per room). Used in OpJoin and similar.</summary>
722 public const byte RoomName = (byte)LiteOpKey.GameId;
723 /// <summary>(250) Code for broadcast parameter of OpSetProperties method.</summary>
724 public const byte Broadcast = (byte)LiteOpKey.Broadcast;
725 /// <summary>(252) Code for list of players in a room. Currently not used.</summary>
726 public const byte ActorList = (byte)LiteOpKey.ActorList;
727 /// <summary>(254) Code of the Actor of an operation. Used for property get and set.</summary>
728 public const byte ActorNr = (byte)LiteOpKey.ActorNr;
729 /// <summary>(249) Code for property set (Hashtable).</summary>
730 public const byte PlayerProperties = (byte)LiteOpKey.ActorProperties;
731 /// <summary>(245) Code of data/custom content of an event. Used in OpRaiseEvent.</summary>
732 public const byte CustomEventContent = (byte)LiteOpKey.Data;
733 /// <summary>(245) Code of data of an event. Used in OpRaiseEvent.</summary>
734 public const byte Data = (byte)LiteOpKey.Data;
735 /// <summary>(244) Code used when sending some code-related parameter, like OpRaiseEvent's event-code.</summary>
736 /// <remarks>This is not the same as the Operation's code, which is no longer sent as part of the parameter Dictionary in Photon 3.</remarks>
737 public const byte Code = (byte)LiteOpKey.Code;
738 /// <summary>(248) Code for property set (Hashtable).</summary>
739 public const byte GameProperties = (byte)LiteOpKey.GameProperties;
740 /// <summary>
741 /// (251) Code for property-set (Hashtable). This key is used when sending only one set of properties.
742 /// If either ActorProperties or GameProperties are used (or both), check those keys.
743 /// </summary>
744 public const byte Properties = (byte)LiteOpKey.Properties;
745 /// <summary>(253) Code of the target Actor of an operation. Used for property set. Is 0 for game</summary>
746 public const byte TargetActorNr = (byte)LiteOpKey.TargetActorNr;
747 /// <summary>(246) Code to select the receivers of events (used in Lite, Operation RaiseEvent).</summary>
748 public const byte ReceiverGroup = (byte)LiteOpKey.ReceiverGroup;
749 /// <summary>(247) Code for caching events while raising them.</summary>
750 public const byte Cache = (byte)LiteOpKey.Cache;
751 /// <summary>(241) Bool parameter of CreateGame Operation. If true, server cleans up roomcache of leaving players (their cached events get removed).</summary>
752 public const byte CleanupCacheOnLeave = (byte)241;
753
754 /// <summary>(240) Code for "group" operation-parameter (as used in Op RaiseEvent).</summary>
755 public const byte Group = LiteOpKey.Group;
756 /// <summary>(239) The "Remove" operation-parameter can be used to remove something from a list. E.g. remove groups from player's interest groups.</summary>
757 public const byte Remove = LiteOpKey.Remove;
758 /// <summary>(238) The "Add" operation-parameter can be used to add something to some list or set. E.g. add groups to player's interest groups.</summary>
759 public const byte Add = LiteOpKey.Add;
760
761
762 /// <summary>(236) Time To Live (TTL) for a room when the last player leaves. Keeps room in memory for case a player re-joins soon. In milliseconds.</summary>
763 public const byte EmptyRoomTTL = 236;
764
765 /// <summary>(235) Time To Live (TTL) for an 'actor' in a room. If a client disconnects, this actor is inactive first and removed after this timeout. In milliseconds.</summary>
766 public const byte PlayerTTL = 235;
767
768
769 /// <summary>(217) This key's (byte) value defines the target custom authentication type/service the client connects with. Used in OpAuthenticate</summary>
770 public const byte ClientAuthenticationType = 217;
771
772 /// <summary>(216) This key's (string) value provides parameters sent to the custom authentication type/service the client connects with. Used in OpAuthenticate</summary>
773 public const byte ClientAuthenticationParams = 216;
774
775 /// <summary>(215) Makes the server create a room if it doesn't exist. OpJoin uses this to always enter a room, unless it exists and is full/closed.</summary>
776 public const byte CreateIfNotExists = 215;
777
778 /// <summary>(215) The JoinMode enum defines which variant of joining a room will be executed: Join only if available, create if not exists or re-join.</summary>
779 /// <remarks>Replaces CreateIfNotExists which was only a bool-value.</remarks>
780 public const byte JoinMode = 215;
781
782 /// <summary>(214) This key's (string or byte[]) value provides parameters sent to the custom authentication service setup in Photon Dashboard. Used in OpAuthenticate</summary>
783 public const byte ClientAuthenticationData = 214;
784
785 /// <summary>(213) Used in matchmaking-related methods and when creating a room to name a lobby (to join or to attach a room to).</summary>
786 public const byte LobbyName = (byte)213;
787
788 /// <summary>(212) Used in matchmaking-related methods and when creating a room to define the type of a lobby. Combined with the lobby name this identifies the lobby.</summary>
789 public const byte LobbyType = (byte)212;
790
791 /// <summary>(211) This (optional) parameter can be sent in Op Authenticate to turn on Lobby Stats (info about lobby names and their user- and game-counts). See: PhotonNetwork.Lobbies</summary>
792 public const byte LobbyStats = (byte)211;
793
794 /// <summary>(210) Used for region values in OpAuth and OpGetRegions.</summary>
795 public const byte Region = (byte)210;
796
797 /// <summary>(209) Path of the WebRPC that got called. Also known as "WebRpc Name". Type: string.</summary>
798 public const byte UriPath = 209;
799
800 /// <summary>(208) Parameters for a WebRPC as: Dictionary<string, object>. This will get serialized to JSon.</summary>
801 public const byte WebRpcParameters = 208;
802
803 /// <summary>(207) ReturnCode for the WebRPC, as sent by the web service (not by Photon, which uses ErrorCode). Type: byte.</summary>
804 public const byte WebRpcReturnCode = 207;
805
806 /// <summary>(206) Message returned by WebRPC server. Analog to Photon's debug message. Type: string.</summary>
807 public const byte WebRpcReturnMessage = 206;
808
809
810 /// <summary>(1) Used in Op FindFriends request. Value must be string[] of friends to look up.</summary>
811 public const byte FindFriendsRequestList = (byte)1;
812
813 /// <summary>(1) Used in Op FindFriends response. Contains bool[] list of online states (false if not online).</summary>
814 public const byte FindFriendsResponseOnlineList = (byte)1;
815
816 /// <summary>(2) Used in Op FindFriends response. Contains string[] of room names ("" where not known or no room joined).</summary>
817 public const byte FindFriendsResponseRoomIdList = (byte)2;
818 }
819
820
821 /// <summary>
822 /// Class for constants. Contains operation codes.
823 /// Pun uses these constants internally.
824 /// </summary>
825 public class OperationCode
826 {
827 /// <summary>(230) Authenticates this peer and connects to a virtual application</summary>
828 public const byte Authenticate = 230;
829 /// <summary>(229) Joins lobby (on master)</summary>
830 public const byte JoinLobby = 229;
831 /// <summary>(228) Leaves lobby (on master)</summary>
832 public const byte LeaveLobby = 228;
833 /// <summary>(227) Creates a game (or fails if name exists)</summary>
834 public const byte CreateGame = 227;
835 /// <summary>(226) Join game (by name)</summary>
836 public const byte JoinGame = 226;
837 /// <summary>(225) Joins random game (on master)</summary>
838 public const byte JoinRandomGame = 225;
839
840 // public const byte CancelJoinRandom = 224; // obsolete, cause JoinRandom no longer is a "process". now provides result immediately
841
842 /// <summary>(254) Code for OpLeave, to get out of a room.</summary>
843 public const byte Leave = (byte)LiteOpCode.Leave;
844 /// <summary>(253) Raise event (in a room, for other actors/players)</summary>
845 public const byte RaiseEvent = (byte)LiteOpCode.RaiseEvent;
846 /// <summary>(252) Set Properties (of room or actor/player)</summary>
847 public const byte SetProperties = (byte)LiteOpCode.SetProperties;
848 /// <summary>(251) Get Properties</summary>
849 public const byte GetProperties = (byte)LiteOpCode.GetProperties;
850
851 /// <summary>(248) Operation code to change interest groups in Rooms (Lite application and extending ones).</summary>
852 public const byte ChangeGroups = (byte)LiteOpCode.ChangeGroups;
853
854 /// <summary>(222) Request the rooms and online status for a list of friends (by name, which should be unique).</summary>
855 public const byte FindFriends = 222;
856
857 /// <summary>(221) Request statistics about a specific list of lobbies (their user and game count).</summary>
858 public const byte GetLobbyStats = 221;
859
860 /// <summary>(220) Get list of regional servers from a NameServer.</summary>
861 public const byte GetRegions = 220;
862
863 /// <summary>(219) WebRpc Operation.</summary>
864 public const byte WebRpc = 219;
865 }
866 }
867
868
869 /// <summary>
870 /// Options for matchmaking rules for OpJoinRandom.
871 /// </summary>
872 public enum MatchmakingMode : byte
873 {
874 /// <summary>Fills up rooms (oldest first) to get players together as fast as possible. Default.</summary>
875 /// <remarks>Makes most sense with MaxPlayers > 0 and games that can only start with more players.</remarks>
876 FillRoom = 0,
877 /// <summary>Distributes players across available rooms sequentially but takes filter into account. Without filter, rooms get players evenly distributed.</summary>
878 SerialMatching = 1,
879 /// <summary>Joins a (fully) random room. Expected properties must match but aside from this, any available room might be selected.</summary>
880 RandomMatching = 2
881 }
882
883 /// <summary>
884 /// Options for optional "Custom Authentication" services used with Photon. Used by OpAuthenticate after connecting to Photon.
885 /// </summary>
886 public enum CustomAuthenticationType : byte
887 {
888 /// <summary>Use a custom authentification service. Currently the only implemented option.</summary>
889 Custom = 0,
890
891 /// <summary>Authenticates users by their Steam Account. Set auth values accordingly!</summary>
892 Steam = 1,
893
894 /// <summary>Authenticates users by their Facebook Account. Set auth values accordingly!</summary>
895 Facebook = 2,
896
897 /// <summary>Disables custom authentification. Same as not providing any AuthenticationValues for connect (more precisely for: OpAuthenticate).</summary>
898 None = byte.MaxValue
899 }
900
901 /// <summary>
902 /// Container for "Custom Authentication" values in Photon (default: user and token). Set AuthParameters before connecting - all else is handled.
903 /// </summary>
904 /// <remarks>
905 /// Custom Authentication lets you verify end-users by some kind of login or token. It sends those
906 /// values to Photon which will verify them before granting access or disconnecting the client.
907 ///
908 /// The Photon Cloud Dashboard will let you enable this feature and set important server values for it.
909 /// https://cloud.exitgames.com/dashboard
910 /// </remarks>
911 public class AuthenticationValues
912 {
913 /// <summary>The type of custom authentication provider that should be used. Currently only "Custom" or "None" (turns this off).</summary>
914 public CustomAuthenticationType AuthType = CustomAuthenticationType.Custom;
915
916 /// <summary>This string must contain any (http get) parameters expected by the used authentication service. By default, username and token.</summary>
917 /// <remarks>Standard http get parameters are used here and passed on to the service that's defined in the server (Photon Cloud Dashboard).</remarks>
918 public string AuthParameters; // { get { return a; } set { a = value; UnityEngine.Debug.LogWarning("AuthParameters set: " + value + " server: " + PhotonNetwork.ServerAddress); } }
919 //private string a;
920
921 /// <summary>After initial authentication, Photon provides a secret for this client / user, which is subsequently used as (cached) validation.</summary>
922 public string Secret; // { get { return s; } set { s = value; UnityEngine.Debug.LogWarning("Secret set: " + value + " server: " + PhotonNetwork.ServerAddress); } }
923 //private string s;
924
925 /// <summary>Data to be passed-on to the auth service via POST. Default: null (not sent). Either string or byte[] (see setters).</summary>
926 public object AuthPostData { get; private set; }
927
928 /// <summary>Sets the data to be passed-on to the auth service via POST.</summary>
929 /// <param name="byteData">Binary token / auth-data to pass on. Empty string will set AuthPostData to null.</param>
930 public virtual void SetAuthPostData(string stringData)
931 {
932 this.AuthPostData = (string.IsNullOrEmpty(stringData)) ? null : stringData;
933 }
934
935 /// <summary>Sets the data to be passed-on to the auth service via POST.</summary>
936 /// <param name="byteData">Binary token / auth-data to pass on.</param>
937 public virtual void SetAuthPostData(byte[] byteData)
938 {
939 this.AuthPostData = byteData;
940 }
941
942 /// <summary>Creates the default parameter string from a user and token value, escaping both. Alternatively set AuthParameters yourself.</summary>
943 /// <remarks>The default parameter string is: "username={user}&token={token}"</remarks>
944 /// <param name="user">Name or other end-user ID used in custom authentication service.</param>
945 /// <param name="token">Token provided by authentication service to be used on initial "login" to Photon.</param>
946 public virtual void SetAuthParameters(string user, string token)
947 {
948 this.AuthParameters = "username=" + System.Uri.EscapeDataString(user) + "&token=" + System.Uri.EscapeDataString(token);
949 }
950
951 public override string ToString()
952 {
953 return AuthParameters + " s: " + Secret;
954 }
955 }
----------------------------------------------------------------------------
Loadbalancing Framework for Photon - Copyright (C) 2011 Exit Games GmbH
Provides the operations needed to use the loadbalancing server app(s).
----------------------------------------------------------------------------
Internally used by PUN, a LoadbalancingPeer provides the operations and enum
definitions needed to use the Photon Loadbalancing server (or the Photon Cloud).
The LoadBalancingPeer does not keep a state, instead this is done by a LoadBalancingClient.
private readonly Dictionary
Joins the lobby on the Master Server, where you get a list of RoomInfos of currently open rooms.
This is an async request which triggers a OnOperationResponse() call.
Leaves the lobby on the Master Server.
This is an async request which triggers a OnOperationResponse() call.
Don't use this method directly, unless you know how to cache and apply customActorProperties.
The PhotonNetwork methods will handle player and room properties for you and call this method.
op[ParameterCode.Broadcast] = true; TODO: check if this also makes sense when creating a room?! broadcast actor properties
gameProperties[GameProperties.IsOpen] = roomOptions.isOpen; TODO: check default value. dont send this then
gameProperties[GameProperties.IsVisible] = roomOptions.isVisible; TODO: check default value. dont send this then
op[ParameterCode.CleanupCacheOnLeave] = true; this is actually setting the room's config
gameProperties[GameProperties.CleanupCacheOnLeave] = true; this is only informational for the clients which join
UnityEngine.Debug.Log("CreateGame: " + SupportClass.DictionaryToString(op));
op[ParameterCode.Broadcast] = true; broadcast actor properties
op[ParameterCode.CleanupCacheOnLeave] = true; this is actually setting the room's config
gameProperties[GameProperties.CleanupCacheOnLeave] = true; this is only informational for the clients which join
UnityEngine.Debug.Log("JoinGame: " + SupportClass.DictionaryToString(op));
Operation to join a random, available room. Overloads take additional player properties.
This is an async request which triggers a OnOperationResponse() call.
If all rooms are closed or full, the OperationResponse will have a returnCode of ErrorCode.NoRandomMatchFound.
If successful, the OperationResponse contains a gameserver address and the name of some room.
Optional. A room will only be joined, if it matches these custom properties (with string keys).
Filters for a particular maxplayer setting. Use 0 to accept any maxPlayer value.
This player's properties (custom and well known).
Selects one of the available matchmaking algorithms. See MatchmakingMode enum for options.
UnityEngine.Debug.LogWarning("OpJoinRandom: " + opParameters.ToStringFull());
Request the rooms and online status for a list of friends (each client must set a unique username via OpAuthenticate).
Used on Master Server to find the rooms played by a selected list of users.
Users identify themselves by using OpAuthenticate with a unique username.
The list of usernames must be fetched from some other source (not provided by Photon).
The server response includes 2 arrays of info (each index matching a friend from the request):
ParameterCode.FindFriendsResponseOnlineList = bool[] of online states
ParameterCode.FindFriendsResponseRoomIdList = string[] of room names (empty string if not in a room)
Array of friend's names (make sure they are unique).
Sends this app's appId and appVersion to identify this application server side.
This is an async request which triggers a OnOperationResponse() call.
This operation makes use of encryption, if that is established before.
See: EstablishEncryption(). Check encryption with IsEncryptionAvailable.
This operation is allowed only once per connection (multiple calls will have ErrorCode != Ok).
Your application's name or ID to authenticate. This is assigned by Photon Cloud (webpage).
The client's version (clients with differing client appVersions are separated and players don't meet).
When authenticating for a specific region, a NameServer will forward you to that region's MasterServer.
else
{
}
Operation to handle this client's interest groups (for events in room).
Note the difference between passing null and byte[0]:
null won't addremove any groups.
byte[0] will addremove all (existing) groups.
First, removing groups is executed. This way, you could leave all groups and join only the ones provided.
Groups to remove from interest. Null will not remove any. A byte[0] will remove all.
Groups to add to interest. Null will not add any. A byte[0] will add all current.
Send an event with custom codetype and any content to the other players in the same room.
Identifies this type of event (and the content). Your game's event codes can start with 0.
Any serializable datatype (including Hashtable like the other OpRaiseEvent overloads).
If this event has to arrive reliably (potentially repeated if it's lost).
Contains (slightly) less often used options. If you pass null, the default options will be used.
opParameters.Clear(); re-used private variable to avoid many new Dictionary() calls (garbage collection)
opParameters[(byte) ParameterCode.EventForward] = true; TURNBASED
Class for constants. These (int) values represent error codes, as defined and sent by the Photon LoadBalancing logic.
Pun uses these constants internally.
server - Photon low(er) level: <= 0
(-3) Operation can't be executed yet (e.g. OpJoin can't be called before being authenticated, RaiseEvent cant be used before getting into a room).
Before you call any operations on the Cloud servers, the automated client workflow must complete its authorization.
In PUN, wait until State is: JoinedLobby (with AutoJoinLobby = true) or ConnectedToMaster (AutoJoinLobby = false)
server - PhotonNetwork: 0x7FFF and down
logic-level error codes start with short.max
Unless you have a plan with "CCU Burst", clients might fail the authentication step during connect.
Affected client are unable to call operations. Please note that players who end a game and return
to the master server will disconnect and re-connect, which means that they just played and are rejected
in the next minute re-connect.
This is a temporary measure. Once the CCU is below the limit, players will be able to connect an play again.
OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen.
Self-hosted Photon servers with a CCU limited license won't let a client connect at all.
Some subscription plans for the Photon Cloud are region-bound. Servers of other regions can't be used then.
Check your master server address and compare it with your Photon Cloud Dashboard's info.
https:cloud.exitgames.comdashboard
OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen.
Self-hosted Photon servers with a CCU limited license won't let a client connect at all.
(32755) Custom Authentication of the user failed due to setup reasons (see Cloud Dashboard) or the provided user data (like username or token). Check error message for details.
(32752) Also known as "PluginReportedError". A call to an external web service (WebHook) failed and in turn, caused the operation to fail. Check the debug message (increase the logging level, if needed).
Class for constants. These (byte) values define "well known" properties for an Actor Player.
Pun uses these constants internally.
"Custom properties" have to use a string-type as key. They can be assigned at will.
public const byte PlayerName = 255; was: 1
Class for constants. These (byte) values are for "well known" roomgame properties used in Photon Loadbalancing.
Pun uses these constants internally.
"Custom properties" have to use a string-type as key. They can be assigned at will.
Class for constants. These values are for events defined by Photon Loadbalancing.
Pun uses these constants internally.
Class for constants. Codes for parameters of Operations and Events.
Pun uses these constants internally.
Codes for Azure TCP Proxy are removed
(251) Code for property-set (Hashtable). This key is used when sending only one set of properties.
If either ActorProperties or GameProperties are used (or both), check those keys.
Class for constants. Contains operation codes.
Pun uses these constants internally.
public const byte CancelJoinRandom = 224; obsolete, cause JoinRandom no longer is a "process". now provides result immediately
Options for matchmaking rules for OpJoinRandom.
Options for optional "Custom Authentication" services used with Photon. Used by OpAuthenticate after connecting to Photon.
Container for "Custom Authentication" values in Photon (default: user and token). Set AuthParameters before connecting - all else is handled.
Custom Authentication lets you verify end-users by some kind of login or token. It sends those
values to Photon which will verify them before granting access or disconnecting the client.
The Photon Cloud Dashboard will let you enable this feature and set important server values for it.
https:cloud.exitgames.comdashboard
public string AuthParameters; { get { return a; } set { a = value; UnityEngine.Debug.LogWarning("AuthParameters set: " + value + " server: " + PhotonNetwork.ServerAddress); } }
private string a;
public string Secret; { get { return s; } set { s = value; UnityEngine.Debug.LogWarning("Secret set: " + value + " server: " + PhotonNetwork.ServerAddress); } }
private string s;
Binary token auth-data to pass on. Empty string will set AuthPostData to null.
Binary token auth-data to pass on.
Name or other end-user ID used in custom authentication service.
Token provided by authentication service to be used on initial "login" to Photon.